package com.sangeng.service.serviceimpl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sangeng.domain.ResponseResult;
import com.sangeng.domain.dto.AddArticleDto;
import com.sangeng.domain.dto.UpdateArticleDto;
import com.sangeng.domain.entity.Article;
import com.sangeng.domain.entity.ArticleTag;
import com.sangeng.domain.vo.ArticleVo;
import com.sangeng.domain.vo.PageVo;
import com.sangeng.enums.AppHttpCodeEnum;
import com.sangeng.exception.SystemException;
import com.sangeng.mapper.ArticleMapper;
import com.sangeng.service.ArticleService;
import com.sangeng.service.ArticleTagService;
import com.sangeng.utils.BeanCopyUtils;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


@RequiredArgsConstructor
@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {
    private final ArticleTagService articleTagService;
    private final ArticleMapper articleMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    //由于可能会出现博文提交成功，但是关联的标签关系没有保存成功的情况，所以把这个操作定义为一个事务，要么就成功，要么就失败
    public ResponseResult<String> add(AddArticleDto articleDto) {
        if(Objects.isNull(articleDto)) {
            throw new SystemException(AppHttpCodeEnum.CONTENTNOTNULL);
        }
        //新增博文 因为我们数据库的article表对应的实体类是article，所以需要进行bean的拷贝
        Article article = BeanCopyUtils.copyBean(articleDto, Article.class);
        //mp的插入操作
        save(article);

        //博文关联的标签列表
        List<ArticleTag> articleTags = articleDto.getTags().stream()
                //关联文章id 标签id
                .map(tagId -> new ArticleTag(article.getId(), tagId))
                .collect(Collectors.toList());

        //添加 博文与标签的关联
        articleTagService.saveBatch(articleTags);
        //响应结果就是状态码 不用响应其他的
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult<PageVo> getArticleByTitle(Integer pageNum, Integer pageSize, String title, String summary) {
        Page<Article> articlePage = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();
        //若有title summary 则加上title summary做模糊查询
        wrapper
                .like(StringUtils.hasText(title), Article::getTitle, title)
                .like(StringUtils.hasText(summary), Article::getSummary, summary);

        //如果没有title,则是纯粹的就是在文章管理那里做分页查询
        //封装数据
        Page<Article> page = page(articlePage, wrapper);
        List<Article> articleList = page.getRecords();
        long total = page.getTotal();
        //打包成分页
        PageVo pageVo = new PageVo(articleList, total);
        return ResponseResult.okResult(pageVo);
    }

    @Override
    public ResponseResult<String> deleteById(List<Long> idList) {
        //逻辑删除
        if (CollectionUtils.isNotEmpty(idList)) {
            boolean update = lambdaUpdate().set(Article::getDelFlag, 1).in(Article::getId, idList).update();
            return update ? ResponseResult.okResult() : ResponseResult.errorResult(AppHttpCodeEnum.ARTICLE_DELETE_ERROR);
        }
        return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_ERROR);
    }

    //修改文章

    //获取原有文章信息
    @Override
    public ResponseResult<ArticleVo> getArticleById(Long id) {
        Article article = articleMapper.selectById(id);
        ArticleVo articleVo = BeanCopyUtils.copyBean(article, ArticleVo.class);
        return ResponseResult.okResult(articleVo);
    }

    //更新文章信息
    @Override
    public ResponseResult<String> updateArticle(UpdateArticleDto articleDto) {
        Article article = BeanCopyUtils.copyBean(articleDto, Article.class);
        boolean update = updateById(article);
        if(update) {
            return ResponseResult.okResult();
        }
        return ResponseResult.errorResult(AppHttpCodeEnum.ARTICLE_UPDATE_ERROR);
    }

}
